package ua.eug.airv1.controllers;

import ua.eug.airv1.map.IOnScreen;
import ua.eug.airv1.map.Tile;
import ua.eug.airv1.map.TilePos;
import ua.eug.airv1.utils.Config;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;

// Screen coordinates only inside this class
public class ScreenController implements IController {

	// for pan/move
	private float panx = -100; 
	private float pany = -100;
	private int zoomPos = 2;
	private final static float zoomPreset[] = { 0.4f, 0.75f, 1f, 1.5f, 2f, 3f, 4f };  
	
	// screen panning
	private float nextX;
	private float nextY;
	private float deltaX;
	private float deltaY;
	private int panMode=0; // 0- no pan
	private float panTimer;
	
	Array<IOnScreen> slaves = new Array<IOnScreen>(false,4);

	protected ScreenController() {
				
	}
	
	private static class SingletonHolder {
        public static final ScreenController HOLDER = new ScreenController();
    }
	
	public static ScreenController getInstance() {
        return SingletonHolder.HOLDER;
    }
 
	public Vector2 XyToStage(int x, int y) {
		float px = 0;
		if (y%2 == 1) { //odd lines
			px = Config.OddRowXOffset;
		}
		float py = y*Config.TileStepY;
		px += x*Config.TileStepX;
		return new Vector2(px,py);
	}

	public void addSlave(IOnScreen g) {
		slaves.add(g);
		g.pan(panx, pany);
		g.zoom(zoomPreset[zoomPos]);
	}
	
	@Override
	public void pan(float deltaX, float deltaY, Tile tile) {
		panx += deltaX;
		if (panx > -Config.TileWidth/2 || panx < -Config.SIZEX*Config.TileStepX+Gdx.graphics.getWidth())
			panx -= deltaX;
		pany += deltaY;
		if (pany > -Config.TileHeight/2 || pany < -Config.SIZEY*Config.TileStepY+Gdx.graphics.getHeight())
			pany -= deltaY;

		//System.out.println("pan (" + panx + ", " + pany + ") ");
		
		for (IOnScreen i : slaves) {
			i.pan(panx, pany);
		}
	}

	public void zoomUp() {
		if (zoomPos < zoomPreset.length-1)
			zoomPos++;
		zoom(zoomPreset[zoomPos]);
	}
	public void zoomDown() {
		if (zoomPos > 0)
			zoomPos--;
		zoom(zoomPreset[zoomPos]);		
	}
	public void zoom (float r) {
		for (IOnScreen i : slaves) {
			i.zoom(r);
		}
		OrderController.getInstance().setZoom(r);
		Gdx.graphics.requestRendering();
	}
	
	@Override
	public void touch(float x, float y, Tile t) {		
	}

	@Override
	public void endTouch() {		
	}

	public void pan(TilePos tp) { // manually pan to tile
		panMode = 10;
		Vector2 p = XyToStage(tp.x, tp.y);
		nextX = -p.x+Gdx.graphics.getWidth()/2;
		nextY = -p.y+Gdx.graphics.getHeight()/2;		
		
		if (nextX > -Config.TileWidth/2 )
			nextX = -Config.TileWidth/2;
		if (nextX < -Config.SIZEX*Config.TileStepX+Gdx.graphics.getWidth())
			nextX = -Config.SIZEX*Config.TileStepX+Gdx.graphics.getWidth();
		if (nextY > -Config.TileHeight/2 )
			nextY = -Config.TileHeight/2;
		if ( nextY < -Config.SIZEY*Config.TileStepY+Gdx.graphics.getHeight())
			nextY = -Config.SIZEY*Config.TileStepY+Gdx.graphics.getHeight();
		
		deltaX = (nextX-panx)/10;
		deltaY = (nextY-pany)/10;
		panTimer = 0;
	}

	public void act(float sec) {
		if (panMode > 0) {
			panTimer +=sec;
			if (panMode < 3 || panMode > 7) {
				// low speed
				if (panTimer >0.08) {
					pan(deltaX, deltaY, null);
					panMode--;
					panTimer = 0;
				}
			} else {
				// high speed
				if (panTimer >0.03) {
					pan(deltaX, deltaY, null);
					panMode--;
					panTimer = 0;
				}
			}
			if (panMode==0)
				Gdx.graphics.setContinuousRendering(false);
		}
	}
}
